package com.ssl.order.config;

import com.ssl.order.constant.ConstantUtils;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableRabbit
public class RabbitMQConfig {
    //进行rabbitmq template的配置
    @Bean(name="rabbitTemplate")
    public AmqpTemplate amqpTemplate(){
        RabbitTemplate rabbitTemplate = new RabbitTemplate();
        rabbitTemplate.setEncoding("UTF-8");
        rabbitTemplate.setMandatory(true);
        //和配置文件中的  publisher-returns: true 配合使用
        rabbitTemplate.setReturnsCallback(returnedMessage -> {
            String messageId = returnedMessage.getMessage().getMessageProperties().getMessageId();
            byte[] body = returnedMessage.getMessage().getBody();
            System.out.println("发送失败的消息，给支持人员发送邮件，消息为：" + new String(body));
        });
        return rabbitTemplate;
    }
    @Bean
    public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(ConnectionFactory connectionFactory){
        SimpleRabbitListenerContainerFactory factory =
                new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(new Jackson2JsonMessageConverter());
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        return factory;
    }

    /**
     * 创建ORDER_EXCHANGE
     * @return
     */
    @Bean(ConstantUtils.ORDER_EXCHANGE)
    public Exchange orderExchange(){
        return ExchangeBuilder.directExchange(ConstantUtils.ORDER_EXCHANGE).durable(true).build();
    }

    /**
     * 创建ORDER_DATA_QUEUE
     * @return
     */
    @Bean(ConstantUtils.ORDER_DATA_QUEUE)
    public Queue orderDataQueue(){
        return new Queue(ConstantUtils.ORDER_DATA_QUEUE);
    }

    /**
     * 将ORDER_DATA_QUEUE与ORDER_EXCHANGE绑定
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding dataQueueBindingExchange(
            @Qualifier(ConstantUtils.ORDER_DATA_QUEUE) Queue queue,
            @Qualifier(ConstantUtils.ORDER_EXCHANGE) Exchange exchange
    ){
        return BindingBuilder.bind(queue).to(exchange).with(ConstantUtils.ORDER_DATA_QUEUE).noargs();
    }

    /**
     * ORDER_CONFIRM_QUEUE 10s超时会通过route进入死信队列
     * @return
     */
    @Bean(ConstantUtils.ORDER_CONFIRM_QUEUE)
    public Queue confirmQueue(){
        return QueueBuilder.durable(ConstantUtils.ORDER_CONFIRM_QUEUE)
                .ttl(10000)
                .deadLetterExchange(ConstantUtils.ORDER_DEAD_EXCHANGE)
                .deadLetterRoutingKey(ConstantUtils.ORDER_DEAD_KEY_ROUTE).build();
    }

    /**
     * 将确认队列和ORDER_EXCHANGE绑定
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding confirmQueueBindingExchange(
            @Qualifier(ConstantUtils.ORDER_CONFIRM_QUEUE) Queue queue,
            @Qualifier(ConstantUtils.ORDER_EXCHANGE) Exchange exchange
    ){
        return BindingBuilder.bind(queue).to(exchange).with(ConstantUtils.ORDER_CONFIRM_QUEUE).noargs();
    }

    /**
     * 创建死信exchange
     * @return
     */
    @Bean
    public DirectExchange dlxExchange(){
        return ExchangeBuilder.directExchange(ConstantUtils.ORDER_DEAD_EXCHANGE).build();
    }

    /**
     * 创建死信队列
     * @return
     */
    @Bean(ConstantUtils.ORDER_DEAD_QUEUE)
    public Queue dlxQueue(){
        return new Queue(ConstantUtils.ORDER_DEAD_QUEUE);
    }

    /**
     * 死信队列和exchange通过route绑定
     * @return
     */
    @Bean
    public Binding dlxBind(){
        return BindingBuilder.bind(dlxQueue()).to(dlxExchange())
                .with(ConstantUtils.ORDER_DEAD_KEY_ROUTE);
    }
    /**
     * 声明queue和exchange到rabbitmq服务中
     */
    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
        RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
        rabbitAdmin.setAutoStartup(true);
        rabbitAdmin.declareExchange(dlxExchange());
        rabbitAdmin.declareExchange(orderExchange());

        rabbitAdmin.declareQueue(dlxQueue());
        rabbitAdmin.declareQueue(orderDataQueue());
        rabbitAdmin.declareQueue(confirmQueue());
        return rabbitAdmin;
    }

}
